package com.xxx.controller;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedDeque;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.xxx.bean.Demo;
import com.xxx.bean.User;
import com.xxx.constant.RedisConstants;
import com.xxx.listener.SystemListener;
import com.xxx.service.DemoService;
import com.xxx.util.AESUtil;
import com.xxx.util.ConnectionUtil;
import com.xxx.util.JedisUtil;
import com.xxx.util.JedisUtil4Persist;
import com.xxx.util.JsonUtil;
import com.xxx.util.PropertyUtil;
import com.xxx.util.RSAUtil;

/**
 * demo Controller
 */
@RestController
@RequestMapping("/test")
public class DemoController extends BaseController {
	
	private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
	
	// 存放异步线程结果的queue
	private static Queue<DeferredResult<Object>> deferredResultQueue = new ConcurrentLinkedDeque<>();
	
	@Autowired
    private DemoService demoService;
	
	@Autowired
	private RabbitTemplate amqpTemplate;

    /**
     * 获取系统启动时间戳
     * http://localhost/test/buildNo
     */
    @RequestMapping("/buildNo")
    public ModelAndView buildNo(){
    	logger.info("enter method buildNo().");
    	ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
    	mav.addObject("buildNo", SystemListener.buildNo);
        return mav;
    }
    
	/**
	 * 异步线程
	 * 需要在web.xml里添加支持：<async-supported>true</async-supported>
	 */
	@RequestMapping("/asyncOrder")
	@ResponseBody
    public Callable<String> asyncOrder(){
    	logger.info("enter method asyncOrder().");
    	System.out.println("主线程开始......." + Thread.currentThread()+"-----"+System.currentTimeMillis());
    	
    	// 副线程处理
    	Callable<String> callable = new Callable<String>() {

			@Override
			public String call() throws Exception {
				System.out.println("副线程开始......." + Thread.currentThread()+"-----"+System.currentTimeMillis());
				Thread.sleep(5000);
				System.out.println("副线程结束......." + Thread.currentThread()+"-----"+System.currentTimeMillis());
				return "order buy successful......."+System.currentTimeMillis();
			}
    	};
    	
    	System.out.println("主线程结束......." + Thread.currentThread()+"-----"+System.currentTimeMillis());
        return callable;
    }
	
	/**
	 * 异步线程创建订单，主线程接收创建订单结果
	 */
	@RequestMapping("/asyncCreateOrder")
	@ResponseBody
    public DeferredResult<Object> asyncCreateOrder(){
    	logger.info("enter method asyncCreateOrder().");
    	DeferredResult<Object> result = new DeferredResult<Object>(5000l, "create order fail...");
    	deferredResultQueue.add(result);
    	// 模拟异步线程往queue里添加元素
//    	new Thread(new Runnable() {
//
//			@Override
//			public void run() {
//				String orderId = UUID.randomUUID().toString();
//				DeferredResult<Object> deferredResult = deferredResultQueue.poll();
//				deferredResult.setResult(orderId);
//			}
//		}).start();
        return result;
    }
	
	/**
	 * 模拟往queue里添加元素
	 * @return
	 */
	@RequestMapping("/getOrder")
	@ResponseBody
    public String getOrder(){
    	logger.info("enter method getOrder().");
    	String orderId = UUID.randomUUID().toString();
		DeferredResult<Object> deferredResult = deferredResultQueue.poll();
		deferredResult.setResult(orderId);
        return "create order successful. orderId="+orderId;
    }
    
    /**
     * 测试DB（多数据源）
     */
    @RequestMapping("/testDb")
    public List<Demo> testDb(HttpServletRequest request){
    	logger.info("enter method testDb().");
    	String db = request.getParameter("db");
    	if(!("1".equals(db)||"2".equals(db))) {
    		db = "1";
    	}
    	List<Demo> records = demoService.getAllRecords(Integer.valueOf(db));
//    	String result = demoService.testResult();
        return records;
    }
    
    /**
     * 测试MyBatis插件
     */
    @RequestMapping("/testMybatis")
    public User testMybatis(){
    	logger.info("enter method testMybatis().");
//    	User user = new User();
//    	user.setId(1);
//    	user.setName("aaaa");
//    	user.setAge(0);
//    	user.setSex("男");
//    	user.setCardno("121125");
//    	demoService.insertUser(user);
    	User user = demoService.getUserById(1);
        return user;
    }
    
    /**
     * 测试DB事务
     */
    @RequestMapping("/testTx")
    public int testTx(){
    	logger.info("enter method testTx().");
    	int n = demoService.testTx();
        return n;
    }
    
    /**
     * 测试redis
     */
    @RequestMapping("/testRedis")
    public ModelAndView testRedis(){
    	logger.info("enter method testRedis().");
    	
    	ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
    	List<Demo> records = demoService.getAllRecords(1);
    	String redisKey = MessageFormat.format(RedisConstants.REDIS_KEY_TEST, "1");
        String redisValue = JsonUtil.encodeJson(records);
        JedisUtil.setex(redisKey, redisValue, 30);
        mav.addObject("redisValue", redisValue);
        
        redisKey = "test:needethfeelist:aok";
		redisValue = "0x12345678901111111111aaaaa";
		JedisUtil.lpush(redisKey, redisValue);
		Long aokListLen = JedisUtil.llen(redisKey);
		mav.addObject("aokListLen", aokListLen);
		
		// 测试redis持久化
        redisKey = "testpersist:needethfeelist:ttf";
		redisValue = "0x09876542222222222222bbbb";
		JedisUtil4Persist.set(redisKey, redisValue);
		String redisValue1 = JedisUtil4Persist.get(redisKey);
		mav.addObject("redisValue1", redisValue1);
        
        return mav;
    }
    
    /**
     * 测试MQ发送
     */
    @RequestMapping("/testMqSendA")
    public Map<String, Object> testMqSendA(){
    	logger.info("enter method testMqSendA().");
    	String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());//24小时制
        //发送消息
        Map<String, Object> msg = new HashMap<String, Object>();
        msg.put("type", "1");
        msg.put("date", date);
        amqpTemplate.convertAndSend("routingKey", JSON.toJSONString(msg)); // convertAndSend转换并发送消息
        return msg;
    }
    
    /**
     * 测试rabbitmq发送
     */
    @RequestMapping("/testMqSendB")
    public String testMqSendB(){
    	logger.info("enter method testMqSendB().");
    	// 获取到连接以及mq通道
        Connection connection;
        String message = "";
		try {
			connection = ConnectionUtil.getConnection();
			// 从连接中创建通道
			Channel channel = connection.createChannel();
			
			String queue = "q_topic_testB";
			
			// 声明（创建）队列
			channel.queueDeclare(queue, false, false, false, null);
			
			// 消息内容
			message = "Hello World!";
			channel.basicPublish("", queue, null, message.getBytes());
			System.out.println(" [x] Sent '" + message + "'");
			//关闭通道和连接
			channel.close();
			connection.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return message;
    }
    
    /**
     * 处理视频课程统计
     */
    @RequestMapping("/video")
    public int video(){
    	logger.info("enter method video().");
    	int cnt = demoService.doVideo();
        return cnt;
    }
    
    /**
     * 测试返回jsp
     * 需要将jsp视图解析器打开
     */
    @RequestMapping("/testJsp")
    public ModelAndView testJsp(){
    	logger.info("enter method testJsp().");
        ModelAndView mav = new ModelAndView("allRecords");
        
        List<Demo> records = demoService.getAllRecords(1);
        mav.addObject("beans", records);
        
        return mav;
    }
    
    /**
     * 测试velocity
     * 需要将velocity视图解析器打开
     */
    @RequestMapping(value="/testVelocity")  
    public ModelAndView testVelocity() {  
    	logger.info("enter method testVelocity().");
    	ModelAndView mav = new ModelAndView("demo");
    	
        String name = "xq";  
        mav.addObject("name", name);
        
        return mav;  
    }
    
    /**
     * 测试RSA
     */
    @SuppressWarnings("rawtypes")
	@RequestMapping("/testRsa")
    public String testRsa(HttpServletRequest request){
    	logger.info("enter method testRsa().");
//    	String srcStr = request.getParameter("srcStr");
    	String json = super.receivePostWithPass(request);
    	if(StringUtils.isEmpty(json)) {
    		logger.error("testRsa | necessary input params is empty.");
        	return "params srcStr is empty!";
    	}
    	Map reqMap = (Map) JSON.parse(json);
    	String srcStr = (String)reqMap.get("srcStr");
    	logger.info("testRsa | srcStr:{}", srcStr);
    	if(StringUtils.isEmpty(srcStr)) {
    		return "srcStr is empty!";
    	}
    	String encryptStr = RSAUtil.getEncodeString(srcStr, RSAUtil.getPublicFile());
    	logger.info("testRsa | encryptStr:{}", encryptStr);
        return encryptStr;
    }
    
    @SuppressWarnings("rawtypes")
	@RequestMapping("/getRsa")
    public String getRsa(HttpServletRequest request){
    	logger.info("enter method getRsa().");
//    	String rsaStr = request.getParameter("rsaStr");
    	String json = super.receivePostWithPass(request);
    	if(StringUtils.isEmpty(json)) {
    		logger.error("getRsa | necessary input params is empty.");
        	return "params rsaStr is empty!";
    	}
    	Map reqMap = (Map) JSON.parse(json);
    	String rsaStr = (String)reqMap.get("rsaStr");
    	logger.info("getRsa | rsaStr:{}", rsaStr);
    	if(StringUtils.isEmpty(rsaStr)) {
    		return "rsaStr is empty!";
    	}
    	String decryptStr = RSAUtil.getDecodeString(rsaStr, RSAUtil.getPrivateFile());
    	logger.info("getRsa | decryptStr:{}", decryptStr);
        return decryptStr;
    }
    
    /**
     * 测试aes加密
     * @throws Exception 
     */
    @RequestMapping("/testAesEncrypt")
    public String testAesEncrypt() throws Exception {
        logger.info("enter method testAesEncrypt()");
        String encrypt = AESUtil.encrypt("helloworld", "testkey");
        logger.info("testAesEncrypt|encrypt:{}", encrypt);
        return encrypt;
    }
    
    /**
     * 测试aes解密
     * @throws Exception 
     */
    @RequestMapping("/testAesDecrypt")
    public String testAesDecrypt() throws Exception {
        logger.info("enter method testAesDecrypt()");
        String encryptMsg = AESUtil.encrypt("helloworld", "testkey");
        logger.info("testAesDecrypt|encryptMsg:{}", encryptMsg);
        String decryptMsg = AESUtil.decrypt(encryptMsg, "testkey");
        logger.info("testAesDecrypt|decryptMsg:{}", decryptMsg);
        return decryptMsg;
    }
    
    /**
     * 测试读取配置文件
     */
    @RequestMapping("/testProp")
    public ModelAndView testProp(){
    	logger.info("enter method testProp().");
    	
    	ModelAndView mav = new ModelAndView(new MappingJackson2JsonView());
    	String testKey = PropertyUtil.getCtxProperty("testKey");
        mav.addObject("testKey", testKey);
        
        return mav;
    }
    
}
